package reading.common;


import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import reading.common.domain.AuthToken;
import reading.common.exception.AbstractHlBaseException;
import reading.common.exception.HlPrivilegeAuthException;
import reading.common.exception.HlUnauthorizedException;
import reading.common.setting.CookieSetting;
import reading.common.setting.SysSetting;
import reading.util.utils.IpUtil;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * @author yangbajing(yangbajing @ gmail.com) on 2016-09-9.
 */
@Component("webUtils")
public class WebUtils {
    private final static Logger logger = getLogger(WebUtils.class);
    private final CookieSetting cookieSetting;

    private final SysSetting sysSetting;


    @Autowired
    public WebUtils(CookieSetting cookieSetting, SysSetting sysSetting) {
        this.cookieSetting = cookieSetting;
        this.sysSetting = sysSetting;

    }

    public Long getUserId() {
        return AuthToken.getFromThreadLocal().get().ownerId;
    }

    public boolean isAdminOrg(String id) {
        return StringUtils.isNoneBlank(id);
    }

    public String getIpFromRequest(HttpServletRequest request) {
        return IpUtil.getIpAddr(request);
    }

    public String findFromHeader(HttpServletRequest request, String headerString) {
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            if (headerString.equalsIgnoreCase(headerName)) {
                return request.getHeader(headerName);
            }
        }
        return "";
    }

    public void writeAuthNotAllow(HttpServletResponse response){
        HlPrivilegeAuthException ex = new HlPrivilegeAuthException();
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        response.setHeader("cache-control", "no-cache");
        response.setHeader("pragma", "no-cache");
        response.setHeader("expires", "0");
        response.setStatus(HttpStatus.FORBIDDEN.value());
        writeByte(response,ex);
    }

    public void writeByte( HttpServletResponse response, AbstractHlBaseException ex){
        PrintWriter out = null;
        try {
            out = response.getWriter();
            Map<String, Object> result = new HashMap<>(3);
            result.put("errCode", ex.getErrCode());
            result.put("errMsg", ex.getMessage());
            result.put("data", ex.getData());
            out.print(JSON.toJSON(result));
        } catch (IOException e) {
            logger.error("返回错误", e);
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
        }
    }

    public void writeAuthException(HttpServletResponse response) {
        HlUnauthorizedException ex = new HlUnauthorizedException();

        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        response.setHeader("cache-control", "no-cache");
        response.setHeader("pragma", "no-cache");
        response.setHeader("expires", "0");
        response.setStatus(HttpStatus.UNAUTHORIZED.value());

        writeByte(response,ex);
    }

    public String getIp() {
        return sysSetting.getIp();
    }

    public Cookie createCookie(String name, String value) {
        Cookie cookie = new Cookie(name, value);
        if (StringUtils.isNoneBlank(cookieSetting.getDomain())) {
            cookie.setDomain(cookieSetting.getDomain());
        }
        if (StringUtils.isNoneBlank(cookieSetting.getPath())) {
            cookie.setPath(cookieSetting.getPath());
        }
        if (cookieSetting.getMaxAge() > 0) {
            cookie.setMaxAge(cookieSetting.getMaxAge());
        }
        cookie.setHttpOnly(cookieSetting.isHttpOnly());
        return cookie;
    }

    /**
     * 清空cookie
     *
     * @param names
     * @return
     */
    public Cookie[] clearCookie(String... names) {
        int i = 0;
        Cookie[] cookies = new Cookie[names.length];
        for (String name : names) {
            Cookie cookie = new Cookie(name, "");
            cookie.setMaxAge(0);
            cookies[i] = cookie;
            i++;
        }
        return cookies;
    }

    public void addCookie(HttpServletResponse response, String name, String value) {
        Cookie domainCookie = createCookie(name, value);
        response.addCookie(domainCookie);
    }

    public void removeCookie(HttpServletRequest request, HttpServletResponse response, String name) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (name.equals(cookie.getName())) {
                    cookie.setValue("");
                    if (StringUtils.isNoneBlank(cookieSetting.getDomain())) {
                        cookie.setDomain(cookieSetting.getDomain());
                    }
                    if (StringUtils.isNoneBlank(cookieSetting.getPath())) {
                        cookie.setPath(cookieSetting.getPath());
                    }
                    cookie.setHttpOnly(cookieSetting.isHttpOnly());
                    cookie.setMaxAge(0);
                    response.addCookie(cookie);
                }
            }
        }
    }

    /**
     * just return the first result, when exists multiple
     */
    public String getValueByRequest(HttpServletRequest request, String name) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie : cookies) {
                if (name.equals(cookie.getName())) {
                    return cookie.getValue();
                }
            }
        }
        return null;
    }

}
